﻿using Furion.DistributedIDGenerator;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using net8.Format;
using net8.Models;
using net8.Models.XiTong;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.Json;

namespace net8.Helper
{
    public class HttpHelper
    {
        static IHttpClientFactory Factory = AppConfig.ServiceProvider.GetService<IHttpClientFactory>()!;
        static JsonSerializerOptions Options = AppConfig.ServiceProvider.GetService<IOptions<JsonOptions>>()!.Value.JsonSerializerOptions;

        public static async Task<string> GetAsync(string url, Dictionary<string, string> headers)
        {
            try
            {
                var client = Factory.CreateClient();
                client.DefaultRequestHeaders.Clear();
                foreach (var key in headers)
                {
                    client.DefaultRequestHeaders.Add(key.Key, key.Value);
                }

                var response = await client.GetAsync(new Uri(url), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
                if (response.IsSuccessStatusCode)
                {
                    string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    return content;
                }
                else
                {
                    return "";
                }
            }
            catch (Exception ex)
            {
                return "";
            }
        }

        public static async Task<T> Get1Async<T>(string url, Dictionary<string, string> headers) where T : IHttpResult
        {
            try
            {
                var client = Factory.CreateClient("");
                client.DefaultRequestHeaders.Clear();
                foreach (var key in headers)
                {
                    client.DefaultRequestHeaders.Add(key.Key, key.Value);
                }

                var response = await client.GetAsync(new Uri(url), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
                if (response.IsSuccessStatusCode)
                {
                    string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    return JsonSerializer.Deserialize<T>(content, Options)!;
                }
                else
                {
                    return ErrorEntity<T>(response.ReasonPhrase);
                }
            }
            catch (Exception ex)
            {
                return ErrorEntity<T>(ex.ToString());
            }
        }

        public static async Task<T> GetAsync<T>(string url, Dictionary<string, string> headers) where T : class, new()
        {
            try
            {
                var client = Factory.CreateClient();
                client.DefaultRequestHeaders.Clear();
                foreach (var key in headers)
                {
                    client.DefaultRequestHeaders.Add(key.Key, key.Value);
                }

                var response = await client.GetAsync(new Uri(url), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
                if (response.IsSuccessStatusCode)
                {
                    string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    return JsonSerializer.Deserialize<T>(content);
                }
                else
                {
                    return CreateEntity<T>(response.ReasonPhrase);
                }
            }
            catch (Exception ex)
            {
                return CreateEntity<T>(ex.ToString());
            }
        }

        public static async Task<T> GetAsync<T>(string url) where T : class, new()
        {
            try
            {
                var client = Factory.CreateClient();
                client.DefaultRequestHeaders.Clear();

                var response = await client.GetAsync(new Uri(url), HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false);
                if (response.IsSuccessStatusCode)
                {
                    string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                    return JsonSerializer.Deserialize<T>(content, Options);
                }
                else
                {
                    return CreateEntity<T>(response.ReasonPhrase);
                }
            }
            catch (Exception ex)
            {
                return CreateEntity<T>(ex.ToString());
            }
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        /// <typeparam name="T">返回数据类型</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="headers">请求头</param>
        /// <returns></returns>
        public static async Task<T> GetJsonAsync<T>(string url, Dictionary<string, string> headers) where T : IHttpResult
        {
            try
            {
                var client = Factory.CreateClient();
                client.DefaultRequestHeaders.Clear();
                foreach (var key in headers)
                {
                    client.DefaultRequestHeaders.Add(key.Key, key.Value);
                }

                var result = await client.GetFromJsonAsync<T>(url).ConfigureAwait(false);//等同GetAsync
                return result;
            }
            catch (HttpRequestException ex)
            {
                return ErrorEntity<T>(ex.ToString());
            }
        }

        /// <summary>
        /// POST请求 无body
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="url">请求地址</param>
        /// <returns></returns>
        public static async Task<T?> PostAsJsonAsync<T>(string url)
        {
            var client = Factory.CreateClient();
            var response = await client.PostAsJsonAsync(url, new { });
            var result = await response.Content.ReadFromJsonAsync<T>();

            return result;
        }

        /// <summary>
        /// POST请求
        /// </summary>
        /// <typeparam name="T">参数类型</typeparam>
        /// <typeparam name="R">返回类型</typeparam>
        /// <param name="url">请求地址</param>
        /// <param name="body">body参数</param>
        /// <returns></returns>
        public static async Task<R?> PostAsJsonAsync<T, R>(string url, T body)
        {
            var client = Factory.CreateClient();
            var response = await client.PostAsJsonAsync(url, body);
            var result = await response.Content.ReadFromJsonAsync<R>();

            return result;
        }

        public static async Task Post<T>(string url)
        {
            var client = Factory.CreateClient();
            await client.PutAsJsonAsync(url, new { });

            var aaa = await client.PostAsJsonAsync(url, new { }, new JsonSerializerOptions());
            aaa.EnsureSuccessStatusCode();
            await aaa.Content.ReadFromJsonAsync<T>();

            using var content = JsonContent.Create(new { Id = 1, Name = "Test" });
            using var response = await client.PostAsync(url, content);
        }

        public static async Task PostAsync<T>(string url)
        {
            var client = Factory.CreateClient();
            StringContent aa = new StringContent("");//application/json
            //StreamContent bb = new StreamContent();//binary
            MultipartContent cc = new MultipartContent();
            MultipartFormDataContent dd = new MultipartFormDataContent(); //multipart/form-data
            //FormUrlEncodedContent ee = new FormUrlEncodedContent();//application/x-www-form-urlencoded

            var aaa = await client.PostAsync(url, cc);
            aaa.EnsureSuccessStatusCode();
            await aaa.Content.ReadFromJsonAsync<T>();

            using var content = JsonContent.Create(new { Id = 1, Name = "Test" });
            using var response = await client.PostAsync(url, content);
        }


        private static T CreateEntity<T>(string errorMsg) where T : class, new()
        {
            T entity = new T();

            var e = Expression.Parameter(typeof(T), "e");
            var property = Expression.Property(e, "Msg");
            var assignString = Expression.Assign(property, Expression.Constant(errorMsg));
            Expression.Lambda<Action<T>>(assignString, e).Compile()(entity);

            return entity;
        }

        private static T ErrorEntity<T>(string errorMsg) where T : IHttpResult
        {
            T entity = Activator.CreateInstance<T>();

            if (string.IsNullOrEmpty(entity.Status))
            {
                entity.Status = "-100";
            }

            var e = Expression.Parameter(typeof(T), "e");
            var property = Expression.Property(e, "Message");
            var assignString = Expression.Assign(property, Expression.Constant(errorMsg));
            Expression.Lambda<Action<T>>(assignString, e).Compile()(entity);

            return entity;
        }
    }

    public interface ThirdResultInterface
    {
        string Code { get; set; }
        string Msg { get; set; }
    }

    /// <summary>
    /// Http返回值约束
    /// </summary>
    public interface IHttpResult
    {
        /// <summary>
        /// 状态 成功失败的标识字段
        /// 可以是int和string
        /// 异常默认值-100
        /// </summary>
        string Status { get; set; }

        /// <summary>
        /// 消息
        /// </summary>
        string Message { get; set; }
    }

    /// <summary>
    /// HTTP请求日志记录和异常处理
    /// </summary>
    public class HttpHander : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response = await base.SendAsync(request, cancellationToken);

            string url = request.RequestUri!.AbsoluteUri;
            string requestHeader = request.Headers.ToString();
            string responseHeader = response.Headers.ToString();
            string body = request.Content == null ? "" : await request.Content.ReadAsStringAsync();
            string result = await response.Content.ReadAsStringAsync();

            string content = "请求地址：" + url + "\r\n请求头：" + requestHeader + "\r\nBody参数：" + body
                + "\r\n响应头：" + responseHeader + "\r\n响应内容：" + result + "\r\n";
            FileHelper.HttpLog(content);

            return response;
        }
    }
}
